\section{【背景】访问硬盘数据控制}\label{ux80ccux666fux8bbfux95eeux786cux76d8ux6570ux636eux63a7ux5236}

bootloader让80386处理器进入保护模式后，下一步的工作就是从硬盘上加载并运行OS。考虑到实现的简单性，bootloader的访问硬盘都是LBA模式的PIO（Program
IO）方式，即所有的I/O操作是通过CPU访问硬盘的I/O地址寄存器完成。

一般主板有2个IDE通道（是硬盘的I/O控制器），每个通道可以接2个IDE硬盘。第一个IDE通道通过访问I/O地址0x1f0-0x1f7来实现，第二个IDE通道通过访问0x170-0x17f实现。每个通道的主从盘的选择通过第6个I/O偏移地址寄存器来设置。具体参数见下表。

\begin{lstlisting}
I/O地址   功能
0x1f0   读数据，当0x1f7不为忙状态时，可以读。
0x1f2   要读写的扇区数，每次读写前，需要指出要读写几个扇区。
0x1f3   如果是LBA模式，就是LBA参数的0-7位
0x1f4   如果是LBA模式，就是LBA参数的8-15位
0x1f5   如果是LBA模式，就是LBA参数的16-23位
0x1f6   第0~3位：如果是LBA模式就是24-27位   第4位：为0主盘；为1从盘
第6位：为1=LBA模式；0 = CHS模式     第7位和第5位必须为1
0x1f7   状态和命令寄存器。操作时先给命令，再读取内容；如果不是忙状态就从0x1f0端口读数据
\end{lstlisting}

硬盘数据是储存到硬盘扇区中，一个扇区大小为512字节。读一个扇区的流程大致为通过outb指令访问I/O地址:0x1f2\textasciitilde{}-0x1f7来发出读扇区命令，通过in指令了解硬盘是否空闲且就绪，如果空闲且就绪，则通过inb指令读取硬盘扇区数据都内存中。可进一步参看bootmain.c中的readsect函数实现来了解通过PIO方式访问硬盘扇区的过程。
